// 生产宏命令函数
function getMacroCommand(): IMacroCommand {
  return {
    commandList: [],
    add(command: BasicCommand | IMacroCommand) {
      this.commandList.push(command);
    },
    execute() {
      for (let i = 0; i < this.commandList.length; i++) {
        this.commandList[i].execute();
      }
    },
  };
}
// 打开空调命令
let openKT: BasicCommand = {
  execute() {
    console.log("空调我打开了.");
  },
};
// 打开电视命令
let openTV: BasicCommand = {
  execute() {
    console.log("电视我打开了。");
  },
};
// 打开音响命令
let openSound: BasicCommand = {
  execute() {
    console.log("音响我打开了");
  },
};
// 电视和音响是连在一起的，封装为一个宏命令
let tv_sound_command = getMacroCommand();
tv_sound_command.add(openTV);
tv_sound_command.add(openSound);
// 关门命令
let closeDoor: BasicCommand = {
  execute() {
    console.log("门我关掉了。");
  },
};
// 开门命令
let openDoor: BasicCommand = {
  execute() {
    console.log("门我打开了。");
  },
};
// 开灯命令
let openLight: BasicCommand = {
  execute() {
    console.log("灯我打开了。");
  },
};
// 关门、开门、开灯封装为一个宏命令
let door_light_command = getMacroCommand();
door_light_command.add(closeDoor);
door_light_command.add(openDoor);
door_light_command.add(openLight);

// 现在组装一个超级遥控器
const superInstrutor = getMacroCommand();
superInstrutor.add(door_light_command);
superInstrutor.add(tv_sound_command);
superInstrutor.add(openKT);

// 测试用例
document.querySelector("#super")?.addEventListener("click", () => {
  superInstrutor.execute();
});

// 为叶节点也实现add接口
let closeLight = {
  execute() {
    console.log("把灯关掉。");
  },
  add(...params: any[]) {
    console.warn("这是一个叶节点，无法进行组合对象。参数列表：", params);
    return;
  },
};

// 测试用例
const lightMacro = getMacroCommand();
lightMacro.add(closeLight);
closeLight.add(lightMacro);

// 扫描文件夹的例子
class Folder implements IFolder {
  // 文件夹类
  name: string;
  inner: (IFolder | IFile)[];
  constructor(name: string) {
    this.name = name;
    this.inner = [];
  }
  add(files: IFile | IFolder) {
    this.inner.push(files);
  }
  scan() {
    console.log(`开始扫描文件夹：${this.name}`);
    for (let i = 0; i < this.inner.length; i++) {
      this.inner[i].scan();
    }
  }
}

class SingleFile implements IFile {
  // 文件类
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  add(...params: any[]) {
    console.warn("不能往文件中再添加文件，传入参数:", params);
  }
  scan() {
    console.log(`开始扫描文件：${this.name}`);
  }
}

// 测试用例--->接下来创建一些对象
const studyfolder = new Folder("学习相关");
const majorfolder = new Folder("专业课");
const csfolder = new Folder("计算机科学");
const fefolder = new Folder("前端开发");
const befolder = new Folder("后端开发");
const rsfile = new SingleFile("遥感原理与应用");
const dpgfile = new SingleFile("数字摄影测量");
const prfile = new SingleFile("模式识别");
const dsfile = new SingleFile("数据结构与算法");
const osfile = new SingleFile("操作系统原理");
const javafile = new SingleFile("深入JVM编程");
const jsfile = new SingleFile("JavaScript高级程序设计");
const bsfile = new SingleFile("深入浏览器内核原理");
// 让它们组合成一颗树
studyfolder.add(majorfolder);
studyfolder.add(csfolder);
csfolder.add(fefolder);
csfolder.add(befolder);
majorfolder.add(rsfile);
majorfolder.add(dpgfile);
majorfolder.add(prfile);
csfolder.add(dsfile);
csfolder.add(osfile);
befolder.add(javafile);
fefolder.add(jsfile);
fefolder.add(bsfile);
// 扫描整个文件夹
studyfolder.scan();

// 改进的文件夹类
class Folder_improved extends Folder {
  parent: Folder_improved | SingleFile_improved | null;
  inner: (Folder_improved | SingleFile_improved)[];
  constructor(name: string) {
    super(name);
    this.inner = [];
    this.parent = null;
  }
  add(...files: (Folder_improved | SingleFile_improved)[]) {
    for (let i = 0; i < files.length; i++) {
      files[i].parent = this; // 在add方法中设定加入文件的父元素
      this.inner.push(files[i]);
    }
  }
  remove() {
    // 新增删除方法
    if (!this.parent) return; // 没有父节点就直接返回
    for (let i = 0; i < this.parent.inner.length; i++) {
      if (this.parent.inner[i] === this) {
        this.parent.inner.splice(i, 1);
      }
    }
  }
}
// 改进的文件类
class SingleFile_improved extends SingleFile {
  parent: Folder_improved | SingleFile_improved | null;
  inner: (Folder_improved | SingleFile_improved)[];
  constructor(name: string) {
    super(name);
    this.parent = null;
    this.inner = [];
  }
  remove() {
    // 新增删除方法
    if (!this.parent) return; // 没有父节点就直接返回
    for (let i = 0; i < this.parent.inner.length; i++) {
      if (this.parent.inner[i] === this) {
        this.parent.inner.splice(i, 1);
      }
    }
  }
}

// 测试用例
const folder1 = new Folder_improved('学习资料');
const folder2 = new Folder_improved('JavaScript');
const file1 = new Folder_improved('深入浅出Node.js');
folder2.add(new SingleFile_improved('JavaScript设计模式'));
folder1.add(folder2);
folder2.remove();
folder1.add(file1);
folder1.scan();// 只剩下了Node.js